//
// Created by twetec on 25-7-21.
//

#include "handle_http_probe_task.h"

#include <boost/json.hpp>
#include <zlib.h>
#include <iconv.h>
#include <brotli/decode.h>
#include <httplib.h>
#include <boost/url.hpp>
#include <base64/base64.h>
#include <bs_thread_pool/BS_thread_pool.hpp>


#include <network_prober/utils/constants.h>

using namespace std::chrono_literals;

namespace network_prober::probe
{
// 线程池
static BS::thread_pool s_iopool{1000};

// static std::string s_decompressBr(const std::string& compressed) {
//     size_t available_in = compressed.size();
//     const uint8_t* next_in = reinterpret_cast<const uint8_t*>(compressed.data());
//
//     // 初始输出缓冲区大小
//     size_t available_out = compressed.size() * 4;
//     std::vector<uint8_t> outbuf(available_out);
//
//     BrotliDecoderState* state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
//     if (!state) {
//         throw std::runtime_error("Failed to create Brotli decoder instance");
//     }
//
//     size_t total_out = 0;
//     BrotliDecoderResult result;
//
//     do {
//         uint8_t* next_out = outbuf.data() + total_out;
//         available_out = outbuf.size() - total_out;
//
//         result = BrotliDecoderDecompressStream(
//             state,
//             &available_in,
//             &next_in,
//             &available_out,
//             &next_out,
//             &total_out
//         );
//
//         if (result == BROTLI_DECODER_RESULT_ERROR) {
//             BrotliDecoderErrorCode error = BrotliDecoderGetErrorCode(state);
//             BrotliDecoderDestroyInstance(state);
//             throw std::runtime_error("Brotli decompression failed with error: " +
//                                    std::to_string(error));
//         }
//
//         // 如果输出缓冲区不足，扩大它
//         if (available_out == 0) {
//             outbuf.resize(outbuf.size() * 2);
//         }
//     } while (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT);
//
//     BrotliDecoderDestroyInstance(state);
//
//     return std::string(reinterpret_cast<const char*>(outbuf.data()), total_out);
// }
//
// static std::string s_decompressDeflate(const std::string& compressed, int windowBits = -15 /* 负数表示原始deflate */) {
//     z_stream zs;
//     memset(&zs, 0, sizeof(zs));
//
//     if (inflateInit2(&zs, windowBits) != Z_OK) {
//         throw std::runtime_error("inflateInit2 failed");
//     }
//
//     zs.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(compressed.data()));
//     zs.avail_in = compressed.size();
//
//     int ret;
//     std::vector<char> outbuffer(32768); // 初始32KB缓冲区
//     std::string out;
//
//     do {
//         zs.next_out = reinterpret_cast<Bytef*>(outbuffer.data());
//         zs.avail_out = outbuffer.size();
//
//         ret = inflate(&zs, 0);
//
//         if (out.size() < zs.total_out) {
//             out.append(outbuffer.data(), zs.total_out - out.size());
//         }
//
//         if (ret != Z_OK && ret != Z_STREAM_END) {
//             inflateEnd(&zs);
//             throw std::runtime_error("inflate failed: " + std::string(zs.msg ? zs.msg : ""));
//         }
//     } while (ret == Z_OK);
//
//     inflateEnd(&zs);
//
//     // 处理没有正确报告数据长度的情况
//     if (zs.total_out > out.size()) {
//         out = out + std::string(outbuffer.data(), zs.total_out - out.size());
//     }
//
//     return out;
// }
//
// static std::string s_decompressGzip(const std::string& compressed) {
//     z_stream zs;
//     memset(&zs, 0, sizeof(zs));
//
//     // 使用 gzip 头部检测
//     if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK) {
//         throw std::runtime_error("inflateInit2 failed");
//     }
//
//     zs.next_in = (Bytef*)compressed.data();
//     zs.avail_in = compressed.size();
//
//     int ret;
//     char outbuffer[32768];
//     std::string outstring;
//
//     // 获取解压后的数据
//     do {
//         zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
//         zs.avail_out = sizeof(outbuffer);
//
//         ret = inflate(&zs, 0);
//
//         if (outstring.size() < zs.total_out) {
//             outstring.append(outbuffer, zs.total_out - outstring.size());
//         }
//     } while (ret == Z_OK);
//
//     inflateEnd(&zs);
//
//     if (ret != Z_STREAM_END) {
//         std::ostringstream oss;
//         oss << "Error during decompression (" << ret << ")";
//         throw std::runtime_error(oss.str());
//     }
//
//     return outstring;
// }
//
// static std::string s_GBKToUTF8(const std::string& gbk_str)
// {
//     iconv_t cd = iconv_open("UTF-8", "GBK");
//     if(cd == (iconv_t)-1) return gbk_str;
//
//     size_t in_len = gbk_str.size();
//     size_t out_len = in_len * 4;
//     char* in_buf = const_cast<char*>(gbk_str.data());
//     std::string utf8_str(out_len, '\0');
//     char* out_buf = &utf8_str[0];
//
//     if(iconv(cd, &in_buf, &in_len, &out_buf, &out_len) == (size_t)-1)
//     {
//         iconv_close(cd);
//         return gbk_str;
//     }
//
//     iconv_close(cd);
//     utf8_str.resize(utf8_str.size() - out_len);
//     return utf8_str;
// }

// HTTPProbeIPv4::HTTPProbeIPv4(
//     std::string_view interface,
//     std::string_view target,
//     std::string_view responseCode,
//     bool ignoreTsl,
//     std::string_view requestMethod, //  目标端口
//     std::string_view requestHeader,  // 地址类型 ipv4/ipv6
//     std::string_view requestBody,
//     bool responseChallenge,
//     std::string_view userName,
//     std::string_view password,
//     bool matchCondition,
//     std::string_view keyWords
// )
//     : m_interface(interface), m_target(target), m_responseCode(responseCode), m_ignoreTsl(ignoreTsl),
//     m_requestMethod(requestMethod), m_requestHeader(requestHeader), m_requestBody(requestBody),
//     m_responseChallenge(responseChallenge), m_userName(userName), m_password(password), m_matchCondition(matchCondition), m_keyWords(keyWords)
// {
//     // 设定连接超时时间
//     m_HTTPClient.set_connect_timeout(std::chrono::seconds(13));
//     // 连接失败或断开后，不尝试自动再次连接
//     m_HTTPClient.set_auto_reconnect(false);
//
//     // 在socket初始化时调用
//     m_HTTPClient.bind_init([this]() {
//         // 绑定请求从哪个网口发送
//         asio::ip::tcp::endpoint endpoint(asio::ip::address_v4::from_string(m_interface), 0);
//         m_HTTPClient.socket().bind(endpoint);
//     });
// }

// void HTTPProbeIPv4::setOnProbedCallback(std::function<void(std::int64_t)> callback)
// {
//     m_onProbedCallback = std::move(callback);
//
//     // 指向当前对象的shared_ptr
//     auto self{shared_from_this()};
//
//     // 连接完成时调用
//     m_HTTPClient.bind_connect([this, self] {
//         // 如果连接错误，则回调，设置延迟为-1
//         if (asio2::get_last_error()) {
//             // 输出错误信息
//             SPDLOG_INFO("HTTP观测目标连接失败：{} - {}", asio2::last_error_val(), asio2::last_error_msg());
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//             // 该代码块执行完， 当前self被释放，当前对象计数器减1.释放当前对象
//         }
//
//         std::string_view targetHost = http::url_to_host(m_target);
//         std::string_view targetPath = http::url_to_path(m_target);
//         std::string_view targetQuery = http::url_to_query(m_target);
//
//         // 设置完响应调用后，发送然探测请求 (默认 http 1.1)
//         std::stringstream ss;
//         ss << targetPath;
//         if (!targetQuery.empty()) {
//            ss << "?" << targetQuery;
//         }
//
//         // 构建http请求
//         http::request<http::string_body> request{utils::g_httpRequestMethods.at(m_requestMethod), ss.str(), 11};
//
//         // 设置host
//         request.set(http::field::host, targetHost);
//         // 设置客户端可接受的内容类型
//         request.set(http::field::accept, "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
//         // 设置客户端可接受的压缩类型
//         request.set(http::field::accept_encoding, "gzip, deflate, br");
//         // 设置客户端编码
//         request.set(http::field::content_type, "text/html; charset=utf-8");
//         // 设置客户端浏览器型号
//         request.set(http::field::user_agent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
//
//         // 设置请求头
//         if (!m_requestHeader.empty()) {
//             // 解析请求头配置
//             boost::json::object requestHeader = boost::json::parse(m_requestHeader).as_object();
//             // 遍历请求头配置
//             for (auto it = requestHeader.begin(); it != requestHeader.end(); ++it) {
//                 // 头部key
//                 std::string headerKey{it->key()};
//                 // 大写转小写
//                 std::transform(headerKey.begin(), headerKey.end(), headerKey.begin(), ::tolower);
//                 // 如果头关键字中不包含这个，则跳过
//                 if (utils::g_httpRequestHeaders.find(headerKey) == utils::g_httpRequestHeaders.end()) continue;
//                 // 如果有匹配的，则设定该值
//                 request.set(utils::g_httpRequestHeaders.at(headerKey), it->value().as_string());
//             }
//         }
//
//         // 设置请求体
//         if (!m_requestBody.empty()) {
//             // 内容类型
//             auto contentType = request.at(http::field::content_type);
//             // 遍历请求体数据, 根据内容类型进行设置
//             if (contentType == "application/json") {
//                 // 如果内容类型是json格式，则直接设置
//                 request.set(http::field::body, m_requestBody);
//             }
//             else if (contentType == "application/x-www-form-urlencoded") {
//                 // 解析请求体数据
//                 boost::json::object requestBody = boost::json::parse(m_requestBody).as_object();
//                 // 请求体字符串
//                 std::stringstream ss;
//                 // 遍历请求体数据，
//                 for (auto it = requestBody.begin(); it != requestBody.end(); ++it) {
//                     ss << it->key() << "=" << it->value().as_string() << "&";
//                 }
//                 std::string body = ss.str();
//                 body.erase(body.find_last_of("&"), 1);
//                 // 整理成 key=value&key=value 再设置
//                 request.set(http::field::body, body);
//             }
//
//             // 重新计算体请求长度
//             request.prepare_payload();
//         }
//
//         // 身份校验(如果需要校验身份)
//         if (m_responseChallenge) {
//             std::stringstream ss;
//             ss << "Basic " << base64_encode(m_userName + ":" + m_password);
//             request.set(http::field::authorization, ss.str());
//         }
//
//         // 异步发送请求
//         m_HTTPClient.async_send(request);
//
//         // 该代码块执行完， 当前self被释放，当前对象计数器减1.释放当前对象
//     });
//
//     // 如果正常连接，则先设置得到响应时调用
//     m_HTTPClient.bind_recv([this, self](http::web_request& req, http::web_response& rep) {
//         // 获取响应码
//         std::uint16_t statusCode = static_cast<std::uint16_t>(rep.result());
//
//         // 如果响应码不是按照要求返回的，则计算延迟
//         if (!std::to_string(statusCode).starts_with(m_responseCode)) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果响应码正确，但不是以2开头，表示没有内容返回，直接计算延迟
//         if (!std::to_string(statusCode).starts_with("2")) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果响应码按照要求传了，并且以2返回，关键字比对为空，则直接计算延迟
//         if (m_keyWords.empty()) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果响应码按要求传了，并且以2返回，并也关键字不为空
//         std::string body{rep.base().body().text()};
//
//         // 如果响应有压缩，则先gzip解压缩
//         if (rep.count(http::field::content_encoding) > 0) {
//             if (rep[http::field::content_encoding].find("gzip") != std::string::npos) {
//                 body = s_decompressGzip(body);
//             }
//             else if (rep[http::field::content_encoding].find("br") != std::string::npos) {
//                 body = s_decompressBr(body);
//             }
//             else if (rep[http::field::content_encoding].find("Deflate") != std::string::npos) {
//                 body = s_decompressDeflate(body);
//             }
//         }
//
//         // 如果是gbk编码的，则先转为utf-8编码
//         if (body.find("charset=gb18030") != std::string::npos || body.find("charset=gbk") != std::string::npos || body.find("charset=GB2312") != std::string::npos) {
//             body = s_GBKToUTF8(body);
//         }
//
//         // 获取页面内容
//         bool isKeywordMatched = false;    // 关键字是否匹配
//         // 关键字集合
//         std::istringstream iss{m_keyWords};
//         // 获取关键字
//         std::string keyword;
//         while (std::getline(iss, keyword, ',')) {
//             // 如果内容中存在关键字
//             if (body.find(keyword) != std::string::npos) {
//                 isKeywordMatched = true;
//                 break;
//             }
//         }
//
//         // 如果关键字设置了，但页面上没有匹配的部分，则延迟为-1
//         if (m_matchCondition && !isKeywordMatched) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果关键字设置了，但页面上没有匹配的部分，则延迟为-1
//         if (!m_matchCondition && isKeywordMatched) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 回调, 返回探测结果
//         m_onProbedCallback(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//         // 断开连接，回收资源
//         m_HTTPClient.stop();
//
//         // 该代码块执行完， 当前self被释放，当前对象计数器减1.释放当前对象
//     });
// }

// void HTTPProbeIPv4::probe()
// {
//     // 建立HTTP连接
//     m_HTTPClient.async_start(asio2::http::url_to_host(m_target), asio2::http::url_to_port(m_target));
//     // 建立连接时，开始计时
//     m_probeStartTime = std::chrono::steady_clock::now();
// }

// HTTPProbeIPv4::~HTTPProbeIPv4()
// {
//     m_HTTPClient.destroy();
// }

HandleHTTPProbeIPv4Awaiter::HandleHTTPProbeIPv4Awaiter(const database::ProbeTaskModel &probeTask)
    : m_interface(probeTask.interface), m_target(probeTask.address), m_responseCode(probeTask.responseCode), m_ignoreTsl(probeTask.ignoreTsl),
    m_requestMethod(probeTask.requestMethod), m_requestHeader(probeTask.requestHeader), m_requestBody(probeTask.requestBody),
    m_responseChallenge(probeTask.responseChallenge), m_userName(probeTask.userName), m_password(probeTask.password), m_matchCondition(probeTask.matchCondition), m_keyWords(probeTask.keyWords)
{
}

bool HandleHTTPProbeIPv4Awaiter::await_ready()
{
    return false;
}

void HandleHTTPProbeIPv4Awaiter::await_suspend(std::coroutine_handle<> handle)
{
    s_iopool.submit_task([this, handle] {
        // 预设延迟未-1
        m_delay = -1;

        // 从目标地址中解析出需要的部分
        boost::urls::url url{m_target};

        // 获取目标主机相关地址
        std::stringstream ss;
        ss << url.scheme() << "://" << url.host();
        // 判断是否有端口号，有的话就拼接
        if (!url.port().empty()) {
            ss << ":" << url.port();
        }
        SPDLOG_INFO("HTTP-IPv4协议目标 - 主机地址：{}", ss.str());

        // 构建请求
        httplib::Client client(ss.str());

        // 设置超时时间(s)
        client.set_max_timeout(8 * 1000);
        // 绑定网口
        client.set_interface(m_interface);

        // 请求和响应都正常时的日志回调
        client.set_logger([&](const httplib::Request& req, const httplib::Response& resp) {
            SPDLOG_INFO("HTTP-IPv4通信正常: {} -> {} :: {} <- {}", m_interface, req.method, ss.str(), resp.body);
        });
        // 请求和响应有不正常时的日志回调
        client.set_error_logger([&](const httplib::Error& err, const httplib::Request* req) {
            SPDLOG_INFO("HTTP-IPv4通信异常： {} -> {} :: {} <- {}", m_interface, req->method, ss.str(), httplib::to_string(err));
        });

        // 创建请求头
        httplib::Headers requestHeader {
            {"Accept", R"(text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7)"},
            {"Accept-Encoding", R"(gzip, deflate, br)"},
            {"Content-Type", R"(text/plain; charset=utf-8)"},
            {"User-Agent", R"(Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36)"}
        };
        // 解析并设置请求头 Accept: application/json\nAccept-Language: zh-CN,zh;q=0.9\nAuthorization: Bearer nV0kDIT7nPHczQ9soXfbThWdDTsCANdXBBfRJiPAdfs\nConnection: keep-alive\nReferer: http://172.16.3.115/\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
        if (!m_requestHeader.empty()) {
            // 字符串位置
            std::size_t searchStart = 0;
            std::size_t searchEnd = m_requestHeader.find("\n", searchStart);

            // 1、将整个header用\n分割为单独的条目
            std::vector<std::string> headerItems;
            headerItems.reserve(10);
            while (searchEnd != std::string::npos) {
                // 找到一个\n时，截取
                headerItems.push_back(m_requestHeader.substr(searchStart, searchEnd - searchStart));
                // 将start指向剩余的字符串
                searchStart = searchEnd + 1;
                // 从新的start位置再次查找
                searchEnd = m_requestHeader.find("\n", searchStart);
            }
            // 最后一段
            headerItems.push_back(m_requestHeader.substr(searchStart));

            // 2、将单独的条目用: 分割为key->value对
            for (auto it = headerItems.begin(); it != headerItems.end(); ++it) {
                // 重置位置
                searchStart = 0;
                searchEnd = it->find(": ", searchStart);

                std::string itemKey;
                while (searchEnd != std::string::npos) {
                    itemKey = it->substr(searchStart, searchEnd - searchStart);
                    searchStart = searchEnd + 2;
                    searchEnd = it->find(": ", searchStart);
                }
                // 3、设置进请求头中
                requestHeader.emplace(itemKey, it->substr(searchStart));
            }
        }

        // 身份校验(如果需要校验身份)
        if (m_responseChallenge) {
            client.set_basic_auth(m_userName, m_password);
        }

        // 请求开始时间
        std::chrono::time_point<std::chrono::steady_clock> detectStartTime = std::chrono::steady_clock::now();
        // 发送请求,返回请求结果
        httplib::Result reqResult;

        // 根据请求方式发起请求
        if (m_requestMethod == "1") {   // GET
            // 拼地址
            std::stringstream ss;
            ss << url.path();   // /v1/obs/page
            if (!url.query().empty()) {
                ss << "?" << url.query();   // /v1/obs/page?pageNum=1&pageSize=100
            }
            SPDLOG_INFO("HTTP-IPv4协议GET目标 - 资源地址：{}", ss.str());
            reqResult = client.Get(ss.str(), requestHeader);
        }
        else if (m_requestMethod == "2") {  // POST
            SPDLOG_INFO("HTTP-IPv4协议POST目标 - 资源地址：{}", url.path());
            reqResult = client.Put(url.path(), requestHeader, m_requestBody, "");
        }
        else if (m_requestMethod == "3") {  // PUT
            SPDLOG_INFO("HTTP-IPv4协议PUT目标 - 资源地址：{}", url.path());
            reqResult = client.Put(url.path(), requestHeader, m_requestBody, "");
        }
        else if (m_requestMethod == "4") {  // DELETE
            SPDLOG_INFO("HTTP-IPv4协议DELETE目标 - 资源地址：{}", url.path());
            reqResult = client.Delete(url.path(), requestHeader, m_requestBody, "");
        }
        else if (m_requestMethod == "5") {  // HEAD
            // 拼地址
            std::stringstream ss;
            ss << url.path();   // /v1/obs/page
            if (!url.query().empty()) {
                ss << "?" << url.encoded_query();   // /v1/obs/page?pageNum=1&pageSize=100
            }
            SPDLOG_INFO("HTTP-IPv4协议HEAD目标 - 资源地址：{}", ss.str());
            reqResult = client.Head(ss.str(), requestHeader);
        }
        else if (m_requestMethod == "6") {  // OPTIONS
            // 拼地址
            std::stringstream ss;
            ss << url.path();   // /v1/obs/page
            if (!url.query().empty()) {
                ss << "?" << url.encoded_query();   // /v1/obs/page?pageNum=1&pageSize=100
            }
            SPDLOG_INFO("HTTP-IPv4协议OPTIONS目标 - 资源地址：{}", ss.str());
            reqResult = client.Options(ss.str(), requestHeader);
        }
        else if (m_requestMethod == "7") {  // PATCH
            SPDLOG_INFO("HTTP-IPv4协议PATCH目标 - 资源地址：{}", url.path());
            reqResult = client.Delete(url.path(), requestHeader, m_requestBody, "");
        }

        // 根据通信结果，作相应处理 (只关注要设置延迟的分支) 如果目标端可达，则如果响应码不是按照要求返回的，则计算延迟
        if (reqResult && std::to_string(reqResult->status).starts_with(m_responseCode)) {    // 如果reqResult为false，表示目标端不可达，则不作任何处理
            // 如果响应码正确，并且是以2开头，表示有内容返回，需要查看是否有匹配关键字
            if (std::to_string(reqResult->status).starts_with("2") && !m_keyWords.empty()) {
                // 获取页面内容
                bool isKeywordMatched = false;    // 关键字是否匹配
                // 关键字集合
                std::istringstream iss{m_keyWords};
                // 获取关键字
                std::string keyword;
                while (std::getline(iss, keyword, ',')) {
                    // 如果内容中存在关键字
                    if (reqResult->body.find(keyword) != std::string::npos) {
                        isKeywordMatched = true;
                        break;
                    }
                }

                // 如果条件相同，表示关键字的匹配和设置匹配的需要相对应，则计算延迟
                if (m_matchCondition == isKeywordMatched) {
                    // 计算延迟
                    m_delay = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - detectStartTime).count();
                    // 输出日志
                    SPDLOG_INFO("观测任务执行成功: {} 延迟", m_delay);
                }
            }
            // 如果响应码正确，但不是以2开头，表示没有内容返回，直接计算延迟
            else {
                // 计算延迟
                    m_delay = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - detectStartTime).count();
                    // 输出日志
                    SPDLOG_INFO("观测任务执行成功: {} 延迟", m_delay);
            }
        }

        // 恢复暂停的协程
        handle.resume();
    });
}

std::int64_t HandleHTTPProbeIPv4Awaiter::await_resume()
{
    return m_delay;
}


// HTTPProbeIPv6::HTTPProbeIPv6(
//     std::string_view interface,
//     std::string_view target,
//     std::string_view responseCode,
//     bool ignoreTsl,
//     std::string_view requestMethod, //  目标端口
//     std::string_view requestHeader,  // 地址类型 ipv4/ipv6
//     std::string_view requestBody,
//     bool responseChallenge,
//     std::string_view userName,
//     std::string_view password,
//     bool matchCondition,
//     std::string_view keyWords
// )
//     : m_interface(interface), m_target(target), m_responseCode(responseCode), m_ignoreTsl(ignoreTsl),
//     m_requestMethod(requestMethod), m_requestHeader(requestHeader), m_requestBody(requestBody),
//     m_responseChallenge(responseChallenge), m_userName(userName), m_password(password), m_matchCondition(matchCondition), m_keyWords(keyWords)
// {
//     // 设定连接超时时间
//     m_HTTPClient.set_connect_timeout(std::chrono::seconds(13));
//     // 连接失败或断开后，不尝试自动再次连接
//     m_HTTPClient.set_auto_reconnect(false);
//
//     // 在socket初始化时调用
//     m_HTTPClient.bind_init([this]() {
//         // 绑定请求从哪个网口发送
//         asio::ip::tcp::endpoint endpoint(asio::ip::address_v6::from_string(m_interface), 0);
//         m_HTTPClient.socket().bind(endpoint);
//     });
// }

// void HTTPProbeIPv6::setOnProbedCallback(std::function<void(std::int64_t)> callback)
// {
//     m_onProbedCallback = std::move(callback);
//
//     // 指向当前对象的shared_ptr
//     auto self{shared_from_this()};
//
//     // 连接完成时调用
//     m_HTTPClient.bind_connect([this, self] {
//         // 如果连接错误，则回调，设置延迟为-1
//         if (asio2::get_last_error()) {
//             // 输出错误信息
//             SPDLOG_INFO("HTTP观测目标连接失败：{} - {}", asio2::last_error_val(), asio2::last_error_msg());
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//             // 该代码块执行完， 当前self被释放，当前对象计数器减1.释放当前对象
//         }
//
//         std::string_view targetHost = http::url_to_host(m_target);
//         std::string_view targetPath = http::url_to_path(m_target);
//         std::string_view targetQuery = http::url_to_query(m_target);
//
//         // 设置完响应调用后，发送然探测请求 (默认 http 1.1)
//         std::stringstream ss;
//         ss << targetPath;
//         if (!targetQuery.empty()) {
//            ss << "?" << targetQuery;
//         }
//
//         // 构建http请求
//         http::request<http::string_body> request{utils::g_httpRequestMethods.at(m_requestMethod), ss.str(), 11};
//
//         // 设置host
//         request.set(http::field::host, targetHost);
//         // 设置客户端可接受的内容类型
//         request.set(http::field::accept, "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
//         // 设置客户端可接受的压缩类型
//         request.set(http::field::accept_encoding, "gzip, deflate, br");
//         // 设置客户端编码
//         request.set(http::field::content_type, "text/html; charset=utf-8");
//         // 设置客户端浏览器型号
//         request.set(http::field::user_agent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
//
//         // 设置请求头
//         if (!m_requestHeader.empty()) {
//             // 解析请求头配置
//             boost::json::object requestHeader = boost::json::parse(m_requestHeader).as_object();
//             // 遍历请求头配置
//             for (auto it = requestHeader.begin(); it != requestHeader.end(); ++it) {
//                 // 头部key
//                 std::string headerKey{it->key()};
//                 // 大写转小写
//                 std::transform(headerKey.begin(), headerKey.end(), headerKey.begin(), ::tolower);
//                 // 如果头关键字中不包含这个，则跳过
//                 if (utils::g_httpRequestHeaders.find(headerKey) == utils::g_httpRequestHeaders.end()) continue;
//                 // 如果有匹配的，则设定该值
//                 request.set(utils::g_httpRequestHeaders.at(headerKey), it->value().as_string());
//             }
//         }
//
//         // 设置请求体
//         if (!m_requestBody.empty()) {
//             // 内容类型
//             auto contentType = request.at(http::field::content_type);
//             // 遍历请求体数据, 根据内容类型进行设置
//             if (contentType == "application/json") {
//                 // 如果内容类型是json格式，则直接设置
//                 request.set(http::field::body, m_requestBody);
//             }
//             else if (contentType == "application/x-www-form-urlencoded") {
//                 // 解析请求体数据
//                 boost::json::object requestBody = boost::json::parse(m_requestBody).as_object();
//                 // 请求体字符串
//                 std::stringstream ss;
//                 // 遍历请求体数据，
//                 for (auto it = requestBody.begin(); it != requestBody.end(); ++it) {
//                     ss << it->key() << "=" << it->value().as_string() << "&";
//                 }
//                 std::string body = ss.str();
//                 body.erase(body.find_last_of("&"), 1);
//                 // 整理成 key=value&key=value 再设置
//                 request.set(http::field::body, body);
//             }
//
//             // 重新计算体请求长度
//             request.prepare_payload();
//         }
//
//         // 身份校验(如果需要校验身份)
//         if (m_responseChallenge) {
//             std::stringstream ss;
//             ss << "Basic " << base64_encode(m_userName + ":" + m_password);
//             request.set(http::field::authorization, ss.str());
//         }
//
//         // 异步发送请求
//         m_HTTPClient.async_send(request);
//
//         // 该代码块执行完， 当前self被释放，当前对象计数器减1.释放当前对象
//     });
//
//     // 如果正常连接，则先设置得到响应时调用
//     m_HTTPClient.bind_recv([this, self](http::web_request& req, http::web_response& rep) {
//         // 获取响应码
//         std::uint16_t statusCode = static_cast<std::uint16_t>(rep.result());
//
//         // 如果响应码不是按照要求返回的，则计算延迟
//         if (!std::to_string(statusCode).starts_with(m_responseCode)) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果响应码正确，但不是以2开头，表示没有内容返回，直接计算延迟
//         if (!std::to_string(statusCode).starts_with("2")) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果响应码按照要求传了，并且以2返回，关键字比对为空，则直接计算延迟
//         if (m_keyWords.empty()) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果响应码按要求传了，并且以2返回，并也关键字不为空
//         std::string body{rep.base().body().text()};
//
//         // 如果响应有压缩，则先gzip解压缩
//         if (rep.count(http::field::content_encoding) > 0) {
//             if (rep[http::field::content_encoding].find("gzip") != std::string::npos) {
//                 body = s_decompressGzip(body);
//             }
//             else if (rep[http::field::content_encoding].find("br") != std::string::npos) {
//                 body = s_decompressBr(body);
//             }
//             else if (rep[http::field::content_encoding].find("Deflate") != std::string::npos) {
//                 body = s_decompressDeflate(body);
//             }
//         }
//
//         // 如果是gbk编码的，则先转为utf-8编码
//         if (body.find("charset=gb18030") != std::string::npos || body.find("charset=gbk") != std::string::npos || body.find("charset=GB2312") != std::string::npos) {
//             body = s_GBKToUTF8(body);
//         }
//
//         // 获取页面内容
//         bool isKeywordMatched = false;    // 关键字是否匹配
//         // 关键字集合
//         std::istringstream iss{m_keyWords};
//         // 获取关键字
//         std::string keyword;
//         while (std::getline(iss, keyword, ',')) {
//             // 如果内容中存在关键字
//             if (body.find(keyword) != std::string::npos) {
//                 isKeywordMatched = true;
//                 break;
//             }
//         }
//
//         // 如果关键字设置了，但页面上没有匹配的部分，则延迟为-1
//         if (m_matchCondition && !isKeywordMatched) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 如果关键字设置了，但页面上没有匹配的部分，则延迟为-1
//         if (!m_matchCondition && isKeywordMatched) {
//             // 回调, 返回探测结果
//             m_onProbedCallback(-1);
//             // 断开连接，回收资源
//             m_HTTPClient.stop();
//             // 结束执行
//             return;
//         }
//
//         // 回调, 返回探测结果
//         m_onProbedCallback(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - m_probeStartTime).count());
//         // 断开连接，回收资源
//         m_HTTPClient.stop();
//
//         // 该代码块执行完， 当前self被释放，当前对象计数器减1.释放当前对象
//     });
// }

// void HTTPProbeIPv6::probe()
// {
//     // 建立HTTP连接
//     m_HTTPClient.async_start(asio2::http::url_to_host(m_target), asio2::http::url_to_port(m_target));
//     // 建立连接时，开始计时
//     m_probeStartTime = std::chrono::steady_clock::now();
// }

// HTTPProbeIPv6::~HTTPProbeIPv6()
// {
//     m_HTTPClient.destroy();
// }

HandleHTTPProbeIPv6Awaiter::HandleHTTPProbeIPv6Awaiter(const database::ProbeTaskModel &probeTask)
    : m_interface(probeTask.interface), m_target(probeTask.address), m_responseCode(probeTask.responseCode), m_ignoreTsl(probeTask.ignoreTsl),
    m_requestMethod(probeTask.requestMethod), m_requestHeader(probeTask.requestHeader), m_requestBody(probeTask.requestBody),
    m_responseChallenge(probeTask.responseChallenge), m_userName(probeTask.userName), m_password(probeTask.password), m_matchCondition(probeTask.matchCondition), m_keyWords(probeTask.keyWords)
{
}

bool HandleHTTPProbeIPv6Awaiter::await_ready()
{
    return false;
}

void HandleHTTPProbeIPv6Awaiter::await_suspend(std::coroutine_handle<> handle)
{
    s_iopool.submit_task([this, handle] {
        // 预设延迟未-1
        m_delay = -1;

        // 从目标地址中解析出需要的部分
        boost::urls::url url{m_target};

        // 获取目标主机相关地址
        std::stringstream ss;
        ss << url.scheme() << "://" << url.host();
        // 判断是否有端口号，有的话就拼接
        if (!url.port().empty()) {
            ss << ":" << url.port();
        }
        SPDLOG_INFO("HTTP-IPv6协议目标 - 主机地址：{}", ss.str());

        // 构建请求
        httplib::Client client(ss.str());

        // 设置超时时间(s)
        client.set_max_timeout(8 * 1000);
        // 绑定网口
        // client.set_interface(m_interface);

        // 请求和响应都正常时的日志回调
        client.set_logger([&](const httplib::Request& req, const httplib::Response& resp) {
            SPDLOG_INFO("HTTP-IPv6通信正常: {} -> {} :: {} <- {}", m_interface, req.method, ss.str(), resp.body);
        });
        // 请求和响应有不正常时的日志回调
        client.set_error_logger([&](const httplib::Error& err, const httplib::Request* req) {
            SPDLOG_INFO("HTTP-IPv6通信异常： {} -> {} :: {} <- {}", m_interface, req->method, ss.str(), httplib::to_string(err));
        });

        // 创建请求头
        httplib::Headers requestHeader {
            {"Accept", R"(text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7)"},
            {"Accept-Encoding", R"(gzip, deflate, br)"},
            {"Content-Type", R"(text/plain; charset=utf-8)"},
            {"User-Agent", R"(Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36)"}
        };
        // 解析并设置请求头 Accept: application/json\nAccept-Language: zh-CN,zh;q=0.9\nAuthorization: Bearer nV0kDIT7nPHczQ9soXfbThWdDTsCANdXBBfRJiPAdfs\nConnection: keep-alive\nReferer: http://172.16.3.115/\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
        if (!m_requestHeader.empty()) {
            // 字符串位置
            std::size_t searchStart = 0;
            std::size_t searchEnd = m_requestHeader.find("\n", searchStart);

            // 1、将整个header用\n分割为单独的条目
            std::vector<std::string> headerItems;
            headerItems.reserve(10);
            while (searchEnd != std::string::npos) {
                // 找到一个\n时，截取
                headerItems.push_back(m_requestHeader.substr(searchStart, searchEnd - searchStart));
                // 将start指向剩余的字符串
                searchStart = searchEnd + 1;
                // 从新的start位置再次查找
                searchEnd = m_requestHeader.find("\n", searchStart);
            }
            // 最后一段
            headerItems.push_back(m_requestHeader.substr(searchStart));

            // 2、将单独的条目用: 分割为key->value对
            for (auto it = headerItems.begin(); it != headerItems.end(); ++it) {
                // 重置位置
                searchStart = 0;
                searchEnd = it->find(": ", searchStart);

                std::string itemKey;
                while (searchEnd != std::string::npos) {
                    itemKey = it->substr(searchStart, searchEnd - searchStart);
                    searchStart = searchEnd + 2;
                    searchEnd = it->find(": ", searchStart);
                }
                // 3、设置进请求头中
                requestHeader.emplace(itemKey, it->substr(searchStart));
            }
        }

        // 身份校验(如果需要校验身份)
        if (m_responseChallenge) {
            client.set_basic_auth(m_userName, m_password);
        }

        // 请求开始时间
        std::chrono::time_point<std::chrono::steady_clock> detectStartTime = std::chrono::steady_clock::now();
        // 发送请求,返回请求结果
        httplib::Result reqResult;

        // 根据请求方式发起请求
        if (m_requestMethod == "1") {   // GET
            // 拼地址
            std::stringstream ss;
            ss << url.path();   // /v1/obs/page
            if (!url.query().empty()) {
                ss << "?" << url.encoded_query();   // /v1/obs/page?pageNum=1&pageSize=100
            }
            SPDLOG_INFO("HTTP-IPv6协议GET目标 - 资源地址：{}", ss.str());
            reqResult = client.Get(ss.str(), requestHeader);
        }
        else if (m_requestMethod == "2") {  // POST
            SPDLOG_INFO("HTTP-IPv6协议POST目标 - 资源地址：{}", url.path());
            reqResult = client.Put(url.path(), requestHeader, m_requestBody, "");
        }
        else if (m_requestMethod == "3") {  // PUT
            SPDLOG_INFO("HTTP-IPv6协议PUT目标 - 资源地址：{}", url.path());
            reqResult = client.Put(url.path(), requestHeader, m_requestBody, "");
        }
        else if (m_requestMethod == "4") {  // DELETE
            SPDLOG_INFO("HTTP-IPv6协议DELETE目标 - 资源地址：{}", url.path());
            reqResult = client.Delete(url.path(), requestHeader, m_requestBody, "");
        }
        else if (m_requestMethod == "5") {  // HEAD
            // 拼地址
            std::stringstream ss;
            ss << url.path();   // /v1/obs/page
            if (!url.query().empty()) {
                ss << "?" << url.encoded_query();   // /v1/obs/page?pageNum=1&pageSize=100
            }
            SPDLOG_INFO("HTTP-IPv6协议HEAD目标 - 资源地址：{}", ss.str());
            reqResult = client.Head(ss.str(), requestHeader);
        }
        else if (m_requestMethod == "6") {  // OPTIONS
            // 拼地址
            std::stringstream ss;
            ss << url.path();   // /v1/obs/page
            if (!url.query().empty()) {
                ss << "?" << url.encoded_query();   // /v1/obs/page?pageNum=1&pageSize=100
            }
            SPDLOG_INFO("HTTP-IPv6协议OPTIONS目标 - 资源地址：{}", ss.str());
            reqResult = client.Options(ss.str(), requestHeader);
        }
        else if (m_requestMethod == "7") {  // PATCH
            SPDLOG_INFO("HTTP-IPv6协议PATCH目标 - 资源地址：{}", url.path());
            reqResult = client.Delete(url.path(), requestHeader, m_requestBody, "");
        }

        // 根据通信结果，作相应处理 (只关注要设置延迟的分支) 如果目标端可达，则如果响应码不是按照要求返回的，则计算延迟
        if (reqResult && std::to_string(reqResult->status).starts_with(m_responseCode)) {    // 如果reqResult为false，表示目标端不可达，则不作任何处理
            // 如果响应码正确，并且是以2开头，表示有内容返回，需要查看是否有匹配关键字
            if (std::to_string(reqResult->status).starts_with("2") && !m_keyWords.empty()) {
                // 获取页面内容
                bool isKeywordMatched = false;    // 关键字是否匹配
                // 关键字集合
                std::istringstream iss{m_keyWords};
                // 获取关键字
                std::string keyword;
                while (std::getline(iss, keyword, ',')) {
                    // 如果内容中存在关键字
                    if (reqResult->body.find(keyword) != std::string::npos) {
                        isKeywordMatched = true;
                        break;
                    }
                }

                // 如果条件相同，表示关键字的匹配和设置匹配的需要相对应，则计算延迟
                if (m_matchCondition == isKeywordMatched) {
                    // 计算延迟
                    m_delay = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - detectStartTime).count();
                    // 输出日志
                    SPDLOG_INFO("观测任务执行成功: {} 延迟", m_delay);
                }
            }
            // 如果响应码正确，但不是以2开头，表示没有内容返回，直接计算延迟
            else {
                // 计算延迟
                m_delay = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - detectStartTime).count();
                // 输出日志
                SPDLOG_INFO("观测任务执行成功: {} 延迟", m_delay);
            }
        }

        // 恢复暂停的协程
        handle.resume();
    });
}

std::int64_t HandleHTTPProbeIPv6Awaiter::await_resume()
{
    return m_delay;
}


}
